package fanshe6;

import Model.User;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.apache.commons.beanutils.BeanUtils;

import javax.sql.DataSource;
import java.io.FileInputStream;
import java.lang.reflect.InvocationTargetException;
import java.sql.*;
import java.util.*;

public class JdbcTools {

    private static DataSource dataSource;

    static {
        try {
            Properties properties = new Properties();
            properties.load(new FileInputStream("src/jdbc1.properties"));
            dataSource = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }

    public static PreparedStatement getPreparedStatement(String sql, Connection connection, Object... parameters) throws SQLException {
        PreparedStatement statement = connection.prepareStatement(sql);
        ParameterMetaData parameterMetaData = statement.getParameterMetaData();
        int count = parameterMetaData.getParameterCount();
        if (count != 0 && parameters != null && parameters.length == count) {
            for (int i = 0; i < count; i++) {
                statement.setObject(i + 1, parameters[i]);
            }
        }
        return statement;
    }

    public static void closeAll(AutoCloseable... resources) {
        for (AutoCloseable resource : resources) {
            if (resource != null) {
                try {
                    resource.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static <T> T queryBean(String sql, Class<T> cls, String... parameters) {
        T t = null;
        try (Connection connection = getConnection();
             PreparedStatement statement = getPreparedStatement(sql, connection, (Object[]) parameters);
             ResultSet resultSet = statement.executeQuery()) {

            ResultSetMetaData metaData = resultSet.getMetaData();
            resultSet.next();
            t = cls.newInstance();
            int columnCount = metaData.getColumnCount();
            for (int i = 1; i <= columnCount; i++) {
                BeanUtils.setProperty(t, metaData.getColumnName(i), resultSet.getObject(i));
            }
        } catch (SQLException throwables) {
            return null;
        } catch (InvocationTargetException e) {
            return null;
        } catch (InstantiationException e) {
            return null;
        } catch (IllegalAccessException e) {
            return null;
        }
        return t;
    }

    public static <T> List<T> select(String sql, Class<T> cls, Object... parameters) throws Exception {
        List<T> list = new ArrayList<>();
        try (Connection connection = getConnection();
             PreparedStatement statement = getPreparedStatement(sql, connection, parameters);
             ResultSet resultSet = statement.executeQuery()) {

            ResultSetMetaData metaData = resultSet.getMetaData();
            while (resultSet.next()) {
                T t = cls.newInstance();
                int columnCount = metaData.getColumnCount();
                for (int i = 1; i <= columnCount; i++) {
                    BeanUtils.setProperty(t, metaData.getColumnName(i), resultSet.getObject(i));
                }
                list.add(t);
            }
        }
        return list;
    }

    public static int update(String sql, Object... parameters) throws Exception {
        int result;
        try (Connection connection = getConnection();
             PreparedStatement statement = getPreparedStatement(sql, connection, parameters)) {
            result = statement.executeUpdate();
        }
        return result;
    }

    public static int delete(String sql, Object... parameters) throws Exception {
        return update(sql, parameters);
    }

    public static int add(String sql, Object... parameters) throws Exception {
        return update(sql, parameters);
    }

    public static ArrayList<Map<String, Object>> queryMapList(String sql, Object... parameters) throws Exception {
        ArrayList<Map<String, Object>> maps = new ArrayList<>();
        try (Connection connection = getConnection();
             PreparedStatement statement = getPreparedStatement(sql, connection, parameters);
             ResultSet resultSet = statement.executeQuery()) {

            ResultSetMetaData metaData = resultSet.getMetaData();
            int columnCount = metaData.getColumnCount();
            while (resultSet.next()) {
                HashMap<String, Object> map = new HashMap<>();
                for (int i = 1; i <= columnCount; i++) {
                    map.put(metaData.getColumnName(i), resultSet.getObject(i));
                }
                maps.add(map);
            }
        }
        return maps;
    }

    public static Object[] queryArray(String sql, Object... parameters) throws Exception {
        Object[] array = null;
        try (Connection connection = getConnection();
             PreparedStatement statement = getPreparedStatement(sql, connection, parameters);
             ResultSet resultSet = statement.executeQuery()) {

            ResultSetMetaData metaData = resultSet.getMetaData();
            int columnCount = metaData.getColumnCount();
            if (resultSet.next()) {
                array = new Object[columnCount];
                for (int i = 0; i < columnCount; i++) {
                    array[i] = resultSet.getObject(i + 1);
                }
            }
        }
        return array;
    }

    public static List<Object[]> queryArray1(String sql, Object... parameters) throws Exception {
        List<Object[]> list = new ArrayList<>();
        try (Connection connection = getConnection();
             PreparedStatement statement = getPreparedStatement(sql, connection, parameters);
             ResultSet resultSet = statement.executeQuery()) {

            ResultSetMetaData metaData = resultSet.getMetaData();
            int columnCount = metaData.getColumnCount();
            while (resultSet.next()) {
                Object[] array = new Object[columnCount];
                for (int i = 0; i < columnCount; i++) {
                    array[i] = resultSet.getObject(i + 1);
                }
                list.add(array);
            }
        }
        return list;
    }

    public static Map<String, Object> queryMap1(String sql, Object... parameters) throws Exception {
        Map<String, Object> map = new HashMap<>();
        try (Connection connection = getConnection();
             PreparedStatement statement = getPreparedStatement(sql, connection, parameters);
             ResultSet resultSet = statement.executeQuery()) {

            ResultSetMetaData metaData = resultSet.getMetaData();
            int columnCount = metaData.getColumnCount();
            if (resultSet.next()) {
                for (int i = 1; i <= columnCount; i++) {
                    map.put(metaData.getColumnName(i), resultSet.getObject(i));
                }
            }
        }
        return map;

    }
}

